package com.mfp.java.testYou.core.utils;

import java.io.IOException;
import java.net.URLEncoder;
import java.text.MessageFormat;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

public class UrlUtils {

	private static final Logger log = Logger.getLogger(UrlUtils.class);

	private UrlUtils() {
	}

	/**
	 * Will redirect user to target page
	 * 
	 * @param request
	 *            HttpServletRequest
	 * @param response
	 *            HttpServletResponse
	 * @param target
	 *            URL (without cPath)
	 * @return true if redirected
	 */
	public static boolean redirectToTarget(HttpServletRequest request, HttpServletResponse response, String target) {

		target = request.getContextPath() + target;

		if (request.getRequestURI().equals(target)) {
			return false;
		}

		try {
			log.info("Redirecting from: " + getTarget(request) + " to " + getTarget(request, target));

			final String encodedUrl = URLEncoder.encode(request.getRequestURL().toString(), "UTF-8");
			final String formattedTarget = MessageFormat.format(target, encodedUrl);

			response.sendRedirect(formattedTarget);

			return true;
		} catch (IOException e) {
			throw new RuntimeException("Can't redirect to " + target + " : " + e.getMessage(), e);
		}
	}

	/**
	 * Will wrap the ServletRequest as a HttpServletRequest
	 * 
	 * @param request
	 * @return
	 */
	public static HttpServletRequest wrapRequest(ServletRequest request) {
		HttpServletRequest httpRequest = null;
		if (request instanceof HttpServletRequest) {
			httpRequest = (HttpServletRequest) request;
		} else {
			throw new RuntimeException("if you managed to throw this exeption, I'll buy you a beer!");
		}
		return httpRequest;
	}

	/**
	 * Will wrap the ServletResponse as a HttpServletResponse
	 * 
	 * @param response
	 * @return
	 */
	public static HttpServletResponse wrapResponse(ServletResponse response) {
		HttpServletResponse httpResponse = null;
		if (response instanceof HttpServletResponse) {
			httpResponse = (HttpServletResponse) response;
		} else {
			throw new RuntimeException("if you managed to throw this exeption, I'll buy you a beer!");
		}
		return httpResponse;
	}

	/**
	 * Will return the target URI without context path
	 * 
	 * @param request
	 *            ServletRequest object
	 * @return URI as String
	 */
	public static String getTarget(ServletRequest request) {
		HttpServletRequest httpRequest = wrapRequest(request);
		String uri = httpRequest.getRequestURI();
		return getTarget(request, uri);
	}

	/**
	 * Will return the target URI without context path
	 * 
	 * @param uri
	 *            uri (possibly with context path)
	 * @return URI as string
	 */
	public static String getTarget(ServletRequest request, String uri) {
		String cPath = wrapRequest(request).getContextPath();
		return uri.replaceAll(cPath, "");
	}

	/**
	 * Will forward user to target page. This is only server side action. User
	 * will not see the difference.
	 * 
	 * @param request
	 *            HttpServletRequest
	 * @param response
	 *            HttpServletResponse
	 * @param target
	 *            URL (without cPath)
	 */
	public static void forwardToTarget(HttpServletRequest request, HttpServletResponse response, String target) {
		RequestDispatcher rd = request.getRequestDispatcher(target);
		try {
			rd.forward(request, response);
		} catch (ServletException e) {
			log.error("Can't forward to " + target + " " + e.getMessage());
		} catch (IOException e) {
			log.error("Can't forward to " + target + " " + e.getMessage());
		}
	}

	/**
	 * Will create a parameter String that can be appendet to the end of an URL.
	 * ex: [a,b,c,d] will become ?a=b&c=d
	 * @param elems odd elems represent names, even elems represent values.
	 * @return formatted String
	 */
	public static String makeParamsString(String... elems){
		if (elems.length%2!=0){
			throw new IllegalArgumentException("Can only take even number of elements");
		}
		StringBuilder sb = new StringBuilder();
		sb.append('?');
		for (int i=0; i<elems.length; i+=2){
			sb.append(elems[i]);
			sb.append('=');
			sb.append(elems[i+1]);
			sb.append('&');
		}
		sb.delete(sb.length()-1, sb.length());
		return sb.toString();
	}
}
